A downloadable liberry for Windows, macOS, and Linux

Quick upload of proclib - it generates castle, ravines, and more...!

What it is: A library and syntax language for structure-centric world/map generation. But what is "structure-centric", you ask? Easy, I'll explain!

Structures can be thought of as complex collections of entities/cells. From this, structures can be made up of other structures to increase the variation and complexity needed for a structure. Examples of structures are: castles, moats, ravines, towns, rooms, and much more.

Towards the end of (easily?) creating complicated maps, I've created this structure generation syntax and library/codebase written in C.

Also, you can make weird faces in it:

...............1...........1............
.............11111......1111111.........
............1111011....111101111........
...........111000001..11100000111.......
............1111011....111101111........
.............11111......1111111.........
...............1...........1............
........................................
........................................
......0.................................
......000000000000000..............0....
.......0...0.0...0.00000000000000000....
........................00....0..00.....

Syntax

Basic Syntax

As it stands, structures are written in plain text files with very simple formatting rules. To begin with, a structures file can contain an (unlimited) amount of structures within it. Each structure can have various settings applied that alters the generation behaviors. The basic variable settings are:

  • flags -- defines the generation behavior using bitflags. Multiple flags can be set by piping them together (ex. "flags CIRCLE|BORDER|ORIGIN")
    • Shape Generation
      • CIRCLE - Bresenham-like ellipse generation
      • RECT - basic "box" generation
    • Shape Modification
      • BORDER - creates an interior border using the current shape
      • IGNORE_EMPTY - ignores cells that are empty (i.e., have no id_s written to them)
    • Structure Placement
      • ORIGIN - places the structure from its center
      • OVERLAP - overlaps the structure on top of other potential structures
  • size_x, size_y -- defines the size of the structure. Values may be: single numbers(e.g., "size_x 4"), percentages(e.g., "size_x 50%" of parent's size), and ranges of either(e.g., "size_x 25%~50%"). If omitted, defaults to 0, 0
  • x, y -- defines the position of the structure. Values may be: single numbers(e.g., "x -4", "x 4"), percentages(e.g., "x -50%", "x 50%"), and ranges of either(e.g., "x -50%~50%"). If omitted, defaults to 0, 0
  • id_1 -- first id of the structure. Values may be: single numbers(e.g., "id_1 2"), ranges(e.g., "id_1 1~4"), or comma-delimited sets of either(e.g., "id_1 2, 1~4")
  • id_2 -- second id of the structure. Follows same rules as id_1
  • Before delving into more complicated aspects of structure definitions, let us use some of the above information to create a simple structure.

    A Simple Circle

    A rudimentary example that creates a variable-sized tower in the middle of the screen would be:

    tower {
      flags CIRCLE
      size_x 12~16
      size_y 9~14
      id_1 0
    }
    

    This would generate structures similar to the following:

    ........................................
    ....................0...................
    .................0000000................
    ................000000000...............
    ...............00000000000..............
    ...............00000000000..............
    ..............0000000000000.............
    ...............00000000000..............
    ...............00000000000..............
    ................000000000...............
    .................0000000................
    ....................0...................
    ........................................
    

    Complex Syntax: Relations

    Every structure can have 3 additional sets of information. The first I will cover is relations. A relation is, as the name implies, a relationship to another structure. In general, relations are used to create sub-structures within a structure.

    Relations are contained with a relations block, and each relation is defined in a similar method as a regular structure. Acceptable settings are:

    • flags -- same as structure flags, but override and/or stack on top of the given structure's flags
    • x, y -- override position settings
    • count -- defines how many times to generate this relation. Values may be: single numbers(e.g., "count 2") or ranges(e.g., "count 2~6"). If omitted, defaults to 1.

    Using this new information, let us expand upon the earlier tower.

    A Simple Tower

    An ellipse by itself is rather boring, but we can spice things up by using relations to create walls:

    tower {
      flags CIRCLE
      size_x 12~16
      size_y 9~14
      id_1 0
      relations {
        tower_walls {
          flags CIRCLE|OVERLAP
        }
      }
    }
    tower_walls {
      flags BORDER
      size_x 100%
      size_y 100%
      id_1 1
    }
    

    This would generate a structure similar to the following:

    ........................................
    ...................1....................
    ................1111111.................
    ..............11100000111...............
    ..............10000000001...............
    .............1100000000011..............
    ..............10000000001...............
    ..............11100000111...............
    ................1111111.................
    ...................1....................
    ........................................
    

    Complex Syntax: Replace

    With the concept of relations out of the way, we can move into the replace functionality. For this example, we're going to use another structure to remove a section of walls from the tower.

    tower {
      flags CIRCLE
      size_x 12~16
      size_y 9~14
      id_1 0
      relations {
        tower_walls {
          flags CIRCLE|BORDER|OVERLAP
        }
        hole {
          x 50%
          y 50%
        }
      }
    }
    tower_walls {
      flags BORDER
      size_x 100%
      size_y 100%
      id_1 1
    }
    hole {
      flags RECT|IGNORE_EMPTY
      size_x 100%
      id_1 0
      replace {
        id_1 1
      }
    }
    

    All we've done is create a new "hole" structure that replaces any overlapping cell with an id_1 of "1" with "0". We've added this structure as a relation to the tower so that it is applied appropriately. The IGNORE_EMPTY flag is only used to prevent the replacement of empty (unset) tiles.

    The resulting replacement would generate something similar to:

    ........................................
    ...................1....................
    ................1111111.................
    ..............11100000111...............
    ..............10000000001...............
    .............1100000000000..............
    ..............10000000000...............
    ..............11100000000...............
    ................1111000.................
    ...................1....................
    ........................................
    

    Complex Syntax: Paths

    The (currently!) final important structure generating concept is that of paths. The first key concept is to realize that paths are generated in a separate pass from initial structures. During structure generation, structures are built and then recorded as "live structures". After this, these live structures are checked for any pathing configuration, and if found, a pathing pass is made. The pathing pass itself generates new live structures for every path "step" made (kept separately from the previous!) and handles the building as per normal operations.

    A path is a configuration within a structure that defines some form of pathing behavior. This includes from/to destination structures, position offsets, structure to use for pathing, pathing algorithm, and others. Acceptable settings for a path are:

    • flags -- these define the behaviors of the pathing
      • Algorithms/Movement
        • DUMB -- doggedly move towards "to" by incrementing or decrementing x and y position. Is stopped by cells that cannot be replaced and are not empty.
        • A* -- uses A* to intelligently move towards position (NOT IMPLEMENTED (YET!))
        • WALK -- only move one cell in one direction at a time (e.g., x+1 OR y+1, not both)
        • WANDER -- some odd chance to randomly move x or y in a direction. Requires an Algorithm.
      • Looping
        • ALL -- attempt to path find to all targets that match the to pathing syntax
      • Etc.
        • FORCE -- if pathing movement fails too many times(>32), force movement anyway
        • UNIQUE -- only look for from/to targets that have not been pathed to/from by this structure
    • to -- pathing syntax for the structure to path to - REQUIRED
    • to_flags -- flags that define a specific "to" behavior
      • ORIGIN -- you guessed it, to_x/to_y values are relative to the center of the target
    • to_x, to_y -- position to path to. Values may be: single numbers(e.g., "1", "-1"), percentages(e.g., "25%"), ranges(e.g., "-25%~25%", "-5~5"), and sets of any(e.g., "1, 25%, -5~5")
    • from -- pathing syntax for the structure to path from. If omitted, defaults to the structure making this path.
    • from_flags -- same as to_flags
    • from_x, from_y -- same as to_x, to_y
    • x, y -- positional data that is applied to each pathing step. Values may be: single numbers(e.g., "-1"), ranges(e.g., "-1~1"), or sets of either(e.g., "-1, -1~1")

    Pathing Syntax

    Pathing syntax, used for to and from in pathing, refers to live structures and uses a straight-forward syntax contained in a single string. An example pathing syntax string could be: ":tower:hole" The following are the single-character "commands" used to acquire a live structure.

    • : -- if the first character of the string, get the global "root" live structure
    • : -- otherwise it is used a position delimiter to specify parent->child
    • ^ -- get parent of this context's live structure

    These can be combined to acquire live structures in complex structures. Examples:

    "tower" -- look for a structure named "tower" in the current context.

    ":tower" -- look for a structure named "tower" in the root context.

    "^tower" -- look for a structure named "tower" in the parent of the current context.

    "^^towers:tower:room" -- look for a structure named "room" in "tower" in "towers" in the parent of the parent of the current context.

    Context is assumed to be the live structure containing the path definitions. 

    Let us use this new-found knowledge to create a road between the towers of two rival wizards.

    The Two Towers

    This example expands on the preceding example by creating a wall-removing path between two towers.

    tower {
      flags CIRCLE
      size_x 8~12
      size_y 7~10
      id_1 0
      relations {
        tower_walls {
          flags CIRCLE|OVERLAP
        }
      }
    }
    tower_walls {
      flags BORDER
      size_x 100%
      size_y 100%
      id_1 1
    }
    dirt_path {
      flags RECT
      size_x 1
      size_y 1
      id_1 0
      replace {
        id_1 1
      }
    }
    towers {
      size_x 100%
      size_y 100% 
      relations {
        tower {
          count 2
          x 10~75%
          y 10~75%
        }
      } 
      paths {
        dirt_path {
          flags DUMB|WALK 
          to tower
          to_flags ORIGIN
          from tower
          from_flags ORIGIN
        }
      }
    }
    

    This would create a scene similar to:

    ...............1........................
    ............1111111.....................
    ...........110000011....................
    ..........11000000011...................
    ...........110000011.......1............
    ............1111100.....1111111.........
    ...............1..00...110000011........
    ...................00..100000001........
    ....................0011000000011.......
    .....................00000000001........
    .......................110000011........
    ........................1111111.........
    ...........................1............
    

    This should give a fairly concise overview of proclib, although there are likely to be massive enhancements and changes in the future. :)

    Other Examples

    Little House by the Lake

    ................................................................
    .........8.......8.........8.8.........88......8.8..............
    ......11111111111.........8....8........................8.......
    ......10000000001.........8....8................................
    .....8100000000018.8........................8....8..............
    ......11111111111.............8.8...........8...............8...
    .......................8........................................
    ......8.......8...........................8.....8...........8..8
    ............................................8...................
    ..8........................8......8.........................8...
    ...8..8....8.......8....8........8..............................
    ........................................8..............8........
    .......8.....................8....8......................8......
    ..........8..8.........88........................8...8...8..8...
    ......8...............8..8.......8.................8.....0....8.
    ......88...............8.................8..........000000000000
    ...8.............8...............................000000000000000
    ..8....8...............88.......................0000000000000000
    ............................8.................000000000000000000
    ....8..................8......8.........8....0000000000000000000
    ........8..............8....................00000000000000000000
    ...................................8.......000000000000000000000
    .....8..........8...8.........8............000000000000000000000
    
    tree {
      flags RECT
      size_x 1
      id_1 8
    }
    
    lake {
      flags CIRCLE|OVERLAP
      size_x 50~75%
      id_1 0
    }
    
    house {
      flags RECT
      size_x 9~14
      size_y 4~7
      id_1 0
      relations {
        house_walls {
          flags RECT
        }
      }
    }
    house_walls {
      flags BORDER|OVERLAP
      size_x 100%
      size_y 100%
      id_1 1
    }
    start {
      size_x 64
      size_y 32
      relations {
        lake {
          count 4~6
          x 50~80%
          y 70~80%
        }
        tree {
          count 64~128
          x 0~100%
          y 0~100%
        }
        house {
          flags OVERLAP
          count 1
          x 10~50%
          y 10~50%
        }
      }
    }
    

    Lumpy Castle

    The structure definition for this one is exceptionally bad and could be refactored.
    .................................................................
    ............................................................9....
    ...9.......1.........................9........1..................
    ........1111111............................1111111...............
    .......110000011..........................1100000119.............
    .......100000001..........................100000001..............
    .......100000001.....................9....100000001......9.......
    ......1100000001111111111111111111111111111000000011.............
    .......100000000000000000000000000000000000000000001.............
    .......100000000000000000000000000000000000000000001.............
    .......110000001111111111111111111111111111100000011....9........
    ........11000011...........9...............11000011..............
    .........100001.............................100001...............
    .........100001..............1......9.......100001...............
    .........100001...........1111111...........100001...............
    .........100001...9......110000011..........100001...............
    .........100001..........100000001..........100001...............
    .........100001........9.100000001..........100001..............9
    .........100001.........11000000011.........100001...............
    .........100001..........100000001..........100001...............
    .........100001..........100000001..........100001...............
    .9.......100001..........110000011..........100001...............
    .........100001...........1111111...........100001...............
    .........100001.....9........1..............100001...............
    ........1100001............................1100001...............
    .......110000011..........................110000011..............
    .......100000001..........................100000001..............
    .......100000001..........................100000001....8.........
    ......1100000001111111111111111111111111111000000011.88888.......
    .......10000000000000000000000000000000000000000001..88888.......
    .9.....10000000000000000000000000000000000000000001.8888888......
    .......11000001111111111111111111111111111110000011..88888.......
    ........1111111............................1111111...88888.......
    ...........1.................................81........8.........
    ...........................................88888.................
    .............................9.............88888.............9...
    ..........................................8888888................
    ...........................................88888.................
    ...........................................88888.................
    .............................................8...................
    .................9........9.......9..............................
    
    lake {
      flags CIRCLE|ORIGIN
      size_x 6~9
      id_1 8
    }
    tree {
      flags RECT|ORIGIN
      size_x 1
      id_1 9
      replace {
        id_1 9
      }
    }
    tower_1 {
      flags CIRCLE|ORIGIN
      size_x 20%
      id_1 0
      relations {
        tower_walls {
          flags OVERLAP
        }
      }
    }
    tower_2 {
      flags CIRCLE|ORIGIN
      size_x 20%
      id_1 0
      relations {
        tower_walls {
          flags OVERLAP
        }
      }
    }
    tower_3 {
      flags CIRCLE|ORIGIN
      size_x 20%
      id_1 0
      relations {
        tower_walls {
          flags OVERLAP
        }
      }
    }
    tower_4 {
      flags CIRCLE|ORIGIN
      size_x 20%
      id_1 0
      relations {
        tower_walls {
          flags OVERLAP
        }
      }
    }
    tower_5 {
      flags CIRCLE|ORIGIN
      size_x 20%
      id_1 0
      relations {
        tower_walls {
          flags OVERLAP
        }
      }
    }
    tower_walls {
      flags CIRCLE|BORDER
      size_x 100%
      size_y 100%
      id_1 1
    }
    
    long_walls {
      size_x 10%
      size_y 10%
      flags RECT|ORIGIN
      id_1 0
      replace {
        id_1 1
      }
      relations {
        long_walls_walls {
        }
      }
    }
    long_walls_walls {
      flags RECT|BORDER|ORIGIN|OVERLAP
      size_x 100%
      size_y 100%
      id_1 1
      replace {
        id_1 0
      }
    }
    
    castle {
      size_x 90%
      size_y 90%
      relations {
        tower_1 {
          x 20%
          y 20%
        }
        tower_2 {
          x 20%
          y 80%
        }
        tower_3 {
          x 80%
          y 20%
        }
        tower_4 {
          x 80%
          y 80%
        }
        tower_5 {
          flags ORIGIN
          x 50%
          y 50%
        }
      }
      paths {
        long_walls {
          flags DUMB|WALK|FORCE
          from tower_1
          from_flags ORIGIN
          to tower_2
          to_flags ORIGIN
          to_x -25%
        }
        long_walls {
          flags DUMB|WALK|FORCE
          from_flags ORIGIN
          from_x 0%
          from_y 0%
          to_flags ORIGIN
          to_x 0%
          to_y 0%
          from tower_1
          to tower_3
        }
        long_walls {
          flags DUMB|WALK|FORCE
          from_flags ORIGIN
          from_x 0%
          from_y 0%
          to_flags ORIGIN
          to_x -25%
          to_y 0%
          from tower_3
          to tower_4
        }
        long_walls {
          flags DUMB|WALK|FORCE
          from_flags ORIGIN
          from_x 0%
          from_y 0%
          to_flags ORIGIN
          to_x 0%
          to_y 0%
          from tower_4
          to tower_2
        }
      }
    }
    start {
      size_x 64~80
      size_y 32~48
      relations {
        castle {
        }
        tree {
          count 16~32
          x 0~100%
          y 0~100%
        }
        lake {
          count 1~2
          x 70~100%
          y 70~100%
        }
      }
    }
    

    Install instructions

    proclib has 3 test programs included:

    • main - terminal-based ASCII structure visualizer
    • sdl - SDL structure visualizer
    • tobmp - structure to BMP

    Windows and OS X have front-ends to the ASCII and SDL renderers.

    See included README.txt for information on program usage and/or compilation.

    proclib_0.1_all.zip contains binaries for:

    • Windows
    • 32-bit Linux
    • 32-bit Intel, 64-bit Intel, and 32-bit PPC Mac OS X


    proclib_0.1.tgz contains the full source code released under the LGPLv3.

    proclib_0.1a.tgz is garbage.

    Download

    Download
    proclib_0.1_all.zip 2 MB
    Download
    proclib_0.1.tgz (source only) 62 kB
    Download
    proclib_0.01a.tgz (source only) 19 kB